package com.liang.manage.auth.facade.server.iml;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liang.manage.auth.facade.dto.role.RoleDTO;
import com.liang.manage.auth.facade.dto.role.RoleOutDTO;
import com.liang.manage.auth.facade.dto.role.RolePermissionsDTO;
import com.liang.manage.auth.facade.dto.role.RoleSearchDTO;
import com.liang.manage.auth.facade.dto.user.UserRoleDTO;
import com.liang.manage.auth.facade.entity.RolePo;
import com.liang.manage.auth.facade.entity.RolePoExample;
import com.liang.manage.auth.facade.mapper.RolePoMapper;
import com.liang.manage.auth.facade.mapstruct.RoleMS;
import com.liang.manage.auth.facade.mapstruct.RoleOutMS;
import com.liang.manage.auth.facade.mapstruct.RoleSsoMS;
import com.liang.manage.auth.facade.server.*;

import com.liang.nansheng.common.auth.PermissionsSsoDTO;
import com.liang.nansheng.common.auth.RoleSsoDTO;
import com.liang.nansheng.common.auth.UserSsoDTO;
import com.liang.nansheng.common.enums.ResponseCode;
import com.liang.nansheng.common.web.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author 王华安
 * @date 2021-04-25 23:26
 */
@Slf4j
@Service
@Component
public class RoleServiceImpl implements RoleService {
    @Autowired
    private RolePoMapper rolePoMapper;

    @Autowired
    private PermissionsService permissionsService;

    @Autowired
    private RolePermissionsService rolePermissionsService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private ProjectService projectService;

    /**
     * 根据id获取角色信息
     *
     * @param id
     * @return
     */
    @Override
    public RoleSsoDTO getSsoById(Integer id) {
        RoleSsoDTO roleSsoDTO = RoleSsoMS.INSTANCE.toDTO(rolePoMapper.selectByPrimaryKey(id));
        // 角色权限
        List<RolePermissionsDTO> rolePermissionsDTOS = rolePermissionsService.getByRoleId(id);
        if (CollectionUtils.isNotEmpty(rolePermissionsDTOS)) {
            // 权限sso
            List<PermissionsSsoDTO> permissionsSsoDTOS = new ArrayList<>();
            rolePermissionsDTOS.forEach(rolePermissionsDTO -> {
                permissionsSsoDTOS.add(permissionsService.getSsoById(rolePermissionsDTO.getPermissionsId()));
            });
            roleSsoDTO.setPermissions(permissionsSsoDTOS);
        }

        return roleSsoDTO;
    }

    /**
     * 新增角色
     *
     * @param roleDTO
     * @param currentUser
     * @return
     */
    @Override
    public Boolean create(RoleDTO roleDTO, UserSsoDTO currentUser) {
        if (StringUtils.isBlank(roleDTO.getName()) || StringUtils.isBlank(roleDTO.getCode()) || roleDTO.getProjectId() == null) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        if (isCodeExist(null, roleDTO.getCode())) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "角色代码重复");
        }
        roleDTO.setState(true);
        roleDTO.setIsDeleted(false);
        roleDTO.setCreateUser(currentUser.getUserId());
        roleDTO.setUpdateUser(currentUser.getUserId());
        LocalDateTime now = LocalDateTime.now();
        roleDTO.setCreateTime(now);
        roleDTO.setUpdateTime(now);
        if (rolePoMapper.insertSelective(RoleMS.INSTANCE.toPo(roleDTO)) <= 0) {
            throw BusinessException.build(ResponseCode.OPERATE_FAIL, "新增角色失败");
        }

        return true;
    }

    /**
     * 分页获取角色
     *
     * @param roleSearchDTO
     * @return
     */
    @Override
    public PageInfo<RoleDTO> getList(RoleSearchDTO roleSearchDTO) {
        PageHelper.startPage(roleSearchDTO.getCurrent(), roleSearchDTO.getSize());

        RolePoExample example = new RolePoExample();
        RolePoExample.Criteria criteria = example.createCriteria().andIsDeletedEqualTo(false);
        if (roleSearchDTO.getProjectId() != null) {
            criteria.andProjectIdEqualTo(roleSearchDTO.getProjectId());
        }
        if (StringUtils.isNotBlank(roleSearchDTO.getCode())) {
            criteria.andCodeLike("%" + roleSearchDTO.getCode() + "%");
        }
        if (StringUtils.isNotBlank(roleSearchDTO.getName())) {
            criteria.andNameLike("%" + roleSearchDTO.getName() + "%");
        }
        if (roleSearchDTO.getState() != null) {
            criteria.andStateEqualTo(roleSearchDTO.getState());
        }
        example.setOrderByClause("`id` desc");

        List<RolePo> rolePos = rolePoMapper.selectByExample(example);
        PageInfo<RoleDTO> pageInfo = RoleMS.INSTANCE.toPage(new PageInfo<>(rolePos));
        // 通过id获取name
        pageInfo.getList().forEach(roleDTO -> {
            roleDTO.setCreateUserName(userService.getNameByIdFromRedis(roleDTO.getCreateUser()));
            roleDTO.setUpdateUserName(userService.getNameByIdFromRedis(roleDTO.getUpdateUser()));
            roleDTO.setProjectName(projectService.getNameByIdFromRedis(roleDTO.getProjectId()));
        });

        return pageInfo;
    }

    /**
     * 更新角色
     *
     * @param roleDTO
     * @param currentUser
     * @return
     */
    @Override
    public Boolean update(RoleDTO roleDTO, UserSsoDTO currentUser) {
        if (StringUtils.isBlank(roleDTO.getName()) || roleDTO.getId() == null) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        if (isCodeExist(roleDTO.getId(), roleDTO.getCode())) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "角色代码重复");
        }
        roleDTO.setState(null);
        roleDTO.setIsDeleted(null);
        roleDTO.setCreateUser(null);
        roleDTO.setCreateTime(null);
        roleDTO.setUpdateUser(currentUser.getUserId());
        roleDTO.setUpdateTime(LocalDateTime.now());
        if (rolePoMapper.updateByPrimaryKeySelective(RoleMS.INSTANCE.toPo(roleDTO)) <= 0) {
            throw BusinessException.build(ResponseCode.OPERATE_FAIL, "更新角色失败");
        }

        return true;
    }

    /**
     * 删除角色
     *
     * @param ids
     * @param currentUser
     * @return
     */
    @Override
    public Boolean delete(List<Integer> ids, UserSsoDTO currentUser) {
        for (Integer id : ids) {
            RoleDTO roleDTO = new RoleDTO();
            roleDTO.setId(id);
            roleDTO.setIsDeleted(true);
            roleDTO.setUpdateTime(LocalDateTime.now());
            roleDTO.setUpdateUser(currentUser.getUserId());
            if (rolePoMapper.updateByPrimaryKeySelective(RoleMS.INSTANCE.toPo(roleDTO)) <= 0) {
                throw BusinessException.build(ResponseCode.OPERATE_FAIL, "删除角色失败");
            }

            // 移除对应的角色权限
            List<RolePermissionsDTO> rolePermissionsDTOS = rolePermissionsService.getByRoleId(id);
            if (CollectionUtils.isNotEmpty(rolePermissionsDTOS)) {
                rolePermissionsService.deleteByRoleId(id, currentUser);
            }
            // 移除对应的用户角色信息
            List<UserRoleDTO> userRoleDTOS = userRoleService.getByRoleIds(Collections.singletonList(id));
            if (CollectionUtils.isNotEmpty(userRoleDTOS)) {
                userRoleService.deleteByRoleId(id, currentUser);
            }
        }

        return true;
    }

    /**
     * 通过角色id获取角色详情
     *
     * @param id
     * @return
     */
    @Override
    public RoleDTO getById(Integer id) {
        RoleDTO roleDTO = RoleMS.INSTANCE.toDTO(rolePoMapper.selectByPrimaryKey(id));
        if (roleDTO == null) {
            return null;
        }
        roleDTO.setCreateUserName(userService.getNameByIdFromRedis(roleDTO.getCreateUser()));
        roleDTO.setUpdateUserName(userService.getNameByIdFromRedis(roleDTO.getUpdateUser()));
        roleDTO.setProjectName(projectService.getNameByIdFromRedis(roleDTO.getProjectId()));

        return roleDTO;
    }

    /**
     * 通过角色code集合获取角色详情
     *
     * @param codes
     * @return
     */
    @Override
    public List<RoleDTO> getByCode(List<String> codes) {
        RolePoExample example = new RolePoExample();
        example.createCriteria().andIsDeletedEqualTo(false)
                .andStateEqualTo(true)
                .andCodeIn(codes);

        return RoleMS.INSTANCE.toDTO(rolePoMapper.selectByExample(example));
    }

    /**
     * 角色判重
     *
     * @param code
     * @param roleId
     * @return
     */
    @Override
    public Boolean isValidRole(String code, Integer roleId) {
        // 已存在
        if (isCodeExist(roleId, code)) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "角色代码已存在");
        }
        return true;
    }

    /**
     * 通过系统获取启用角色
     *
     * @param projectId
     * @return
     */
    @Override
    public List<RoleOutDTO> getEnableRoleByProjectId(Integer projectId) {
        RolePoExample example = new RolePoExample();
        example.createCriteria().andIsDeletedEqualTo(false)
                .andStateEqualTo(true)
                .andProjectIdEqualTo(projectId);

        return RoleOutMS.INSTANCE.toDTO(rolePoMapper.selectByExample(example));
    }

    /**
     * 获取全部启用角色
     *
     * @return
     */
    @Override
    public List<RoleDTO> getEnableRoleAll() {
        RolePoExample example = new RolePoExample();
        RolePoExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeletedEqualTo(false)
                .andStateEqualTo(true);
        example.setOrderByClause("`id` desc");

        List<RolePo> rolePos = rolePoMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(rolePos)) {
            return Collections.emptyList();
        }
        List<RoleDTO> roleDTOS = RoleMS.INSTANCE.toDTO(rolePos);
        // 通过id获取name
        roleDTOS.forEach(roleDTO -> {
            roleDTO.setCreateUserName(userService.getNameByIdFromRedis(roleDTO.getCreateUser()));
            roleDTO.setUpdateUserName(userService.getNameByIdFromRedis(roleDTO.getUpdateUser()));
            roleDTO.setProjectName(projectService.getNameByIdFromRedis(roleDTO.getProjectId()));
        });

        return roleDTOS;
    }

    /**
     * 判断角色是否已经存在
     *
     * @param roleId 角色id
     * @param code   角色代码
     * @return
     */
    private boolean isCodeExist(Integer roleId, String code) {
        RolePoExample example = new RolePoExample();
        // 角色代码或名称 ( a = ? and b = ? ) or ( a = ? and c = ? )
        example.createCriteria().andIsDeletedEqualTo(false)
                .andCodeEqualTo(code);
        List<RolePo> rolePos = rolePoMapper.selectByExample(example);
        if (rolePos.size() > 1) {
            return true;
        } else if (rolePos.size() == 1) {
            // 更新时roleId是有值的
            return !rolePos.get(0).getId().equals(roleId);
        }
        return false;
    }

}
